package com.logistics.heart.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.logistics.command.service.CommandService;
import com.logistics.delivery.entity.domain.Delivery;
import com.logistics.delivery.entity.model.DeliveryRow;
import com.logistics.delivery.service.DeliveryService;
import com.logistics.heart.entity.domain.Heart;
import com.logistics.heart.entity.model.HeartRow;
import com.logistics.heart.entity.model.HeartSave;
import com.logistics.heart.mapper.HeartMapper;
import com.logistics.map.entity.domain.MapComponents;
import com.logistics.map.service.MapComponentsService;
import com.logistics.pick.service.PickContainerService;
import com.logistics.rcs.entity.model.RcsCoordinateRow;
import com.logistics.rcs.service.RcsService;
import com.logistics.utils.constants.Constants;
import com.logistics.utils.constants.Message;
import com.logistics.utils.exception.MessageException;
import com.logistics.utils.message.Manager;
import com.logistics.utils.tool.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class HeartService extends ServiceImpl<HeartMapper, Heart> {

    @Autowired
    private DeliveryService deliveryService;

    @Autowired
    private MapComponentsService mapComponentsService;

    @Autowired
    @Lazy
    private CommandService commandService;

    @Autowired
    private RcsService rcsService;

    @Autowired
    private PickContainerService pickContainerService;

    @Transactional
    public void merge(List<HeartSave> hearts) {
        List<Heart> list = this.list();
        List<String> ips = list.stream().map(e -> e.getIp()).collect(Collectors.toList());
        hearts.stream().forEach(e -> {
            if (ips.contains(e.getIp())) {
                Heart row = list.stream().filter(item -> StringUtils.isEquals(item.getIp(), e.getIp()))
                        .findFirst().get();
                // 待命的设备
                if(StringUtils.isEquals(row.getState(), Constants.HANDLER_STATE_STANDBY) &&
                        StringUtils.isEquals(row.getHandleState(), Constants.HANDLER_STATE_STANDBY) &&
                        StringUtils.isEquals(e.getHandleState(), Constants.HANDLER_STATE_STANDBY) &&
                        StringUtils.isEquals(row.getConnectState(), Constants.CONNECTION_STATE_SUCCESS) &&
                        StringUtils.isEquals(e.getConnectState(), Constants.CONNECTION_STATE_SUCCESS)
//                        && StringUtils.isEquals(row.getTaskState(), Constants.TASK_STATE_SUCCESS)
                ){
                    genTaskScheduling(row.getIp());
                }
                this.update(Heart.build(e), new LambdaQueryWrapper<Heart>().eq(Heart::getIp, e.getIp()));
            } else {
                // 待命的设备
                if(StringUtils.isEquals(e.getHandleState(), Constants.HANDLER_STATE_STANDBY)){
                    genTaskScheduling(e.getIp());
                }
                this.save(Heart.build(e));
            }
        });
    }

    /**
     * 查找所有信息数据
     * @return
     */
    public List<HeartRow> hearts() {
        List<HeartRow> result = this.list().stream().map(HeartRow::build).collect(Collectors.toList());
        List<String> paths = result.stream().filter(e -> StringUtils.isNotNull(e.getPath()))
                .flatMap(e -> Arrays.stream(e.getPath().split(","))
                        .map(item -> item.split("-")[1])).
                collect(Collectors.toList());
        List<String> ips = result.stream().map(HeartRow::getIp).collect(Collectors.toList());
        // 查找配送任务
        List<Delivery> deliveries = deliveryService.list(new LambdaQueryWrapper<Delivery>().in(Delivery::getAgv, ips)
                .eq(Delivery::getStatus, Constants.DELIVERY_STATE_IN));
        if(!paths.isEmpty() && !deliveries.isEmpty()){
            // 查找所有点位的坐标信息
            Map<String, RcsCoordinateRow> coordinateMaps = rcsService.coordinateRows(paths).stream()
                    .collect(Collectors.toMap(RcsCoordinateRow::getPoint, e -> e));
            // 查找目的站点
//            Map<String, String> locationMaps = mapComponentsService.list(new LambdaQueryWrapper<MapComponents>().in(MapComponents::getLocation,
//                            deliveries.stream().map(Delivery::getEndStation).collect(Collectors.toList()))).stream()
//                    .collect(Collectors.toMap(MapComponents::getLocation, MapComponents::getUuid));
            // 目的地站点
//            Map<String, String> deliverLocationMaps = deliveries.stream().filter(item -> StringUtils.isNotNull(item.getAgv())
//                            && StringUtils.isNotNull(item.getEndStation())).
//                    collect(Collectors.toMap(Delivery::getAgv, e -> locationMaps.get(e.getEndStation())));
            // 将点位转换成坐标
            result.stream().filter(item -> StringUtils.isNotNull(item.getPath()) &&
                    StringUtils.isEquals(item.getConnectState(), Constants.CONNECTION_STATE_SUCCESS)).forEach(e -> {
                List<String> coordinates = StringUtils.splitToList(e.getPath(), ",")
                        .stream().filter(key -> StringUtils.isNotNull(coordinateMaps.get(key.split("-")[1])))
                        .map(key -> coordinateMaps.get(key.split("-")[1]).getX()+","+coordinateMaps.get(key.split("-")[1]).getY())
                        .collect(Collectors.toList());
//                e.setTargetLocationId(deliverLocationMaps.get(e.getIp()));
                e.setPath(StringUtils.listToString(coordinates, "|"));
            });
        }
        return result;
    }

    /**
     * 车辆归位
     * @param ip
     */
    public void homing(String ip) throws MessageException, JsonProcessingException {
        Heart heart = this.getOne(new LambdaQueryWrapper<Heart>().eq(Heart::getIp, ip));
        if(StringUtils.isNull(heart)){
            throw new MessageException("车辆编码不正确");
        }
        List<Delivery> result = deliveryService.list(new LambdaQueryWrapper<Delivery>().eq(Delivery::getStatus, Constants.DELIVERY_STATE_STANDBY));
        if(StringUtils.isNull(result) || result.size() == 0){
            List<MapComponents> mapComponents = mapComponentsService.
                    list(new LambdaQueryWrapper<MapComponents>().eq(MapComponents::getClazz, Constants.COMPONENTS_TYPE_CAR_LOCATION));
            if(StringUtils.isNull(mapComponents) || mapComponents.size() == 0){
                throw new MessageException("没找到停车位");
            }
            // 发送点到点指令
            commandService.pointToPoint(ip, mapComponents.get(0).getLocation());
        }
        // 状态回写
        this.update(Heart.build(Constants.HANDLER_STATE_STANDBY), new LambdaQueryWrapper<Heart>().eq(Heart::getId, heart.getId()));
    }

    /**
     * 查找心跳信息根据ip
     * @param ip
     * @return
     * @throws MessageException
     */
    public HeartRow heartByIp(String ip) throws MessageException {
        if(StringUtils.isNull(ip)){
            throw new MessageException(Manager.getMessage(Message.MSG1005.getCode()));
        }
        Heart result = this.getOne(new LambdaQueryWrapper<Heart>().eq(Heart::getIp, ip));
        if(StringUtils.isNull(result)){
            throw new MessageException(Manager.getMessage(Message.MSG1019.getCode()));
        }
        return HeartRow.build(result);
    }

    /**
     * 更新状态
     * @param state
     * @param ip
     */
    public void updateStateByIp(String state, String ip){
        this.update(Heart.build(state), new LambdaQueryWrapper<Heart>()
                .eq(Heart::getIp, ip)
                .eq(Heart::getConnectState, Constants.CONNECTION_STATE_SUCCESS)
                .eq(Heart::getHandleState, Constants.HANDLER_STATE_STANDBY));
    }

    /**
     * 生成任务
     * @param deviceId
     */
    private void genTaskScheduling(String deviceId){
        MapComponents agvInfo = mapComponentsService.agvTypeByDeviceId(deviceId);
            if(StringUtils.isNotNull(agvInfo) && StringUtils.isNotNull(agvInfo.getAgvType())){
            List<DeliveryRow> deliveryRows = deliveryService.listByStatus(Constants.DELIVERY_STATE_STANDBY,
                    agvInfo.getAgvType(), agvInfo.getZone());
            if(!deliveryRows.isEmpty()){
                DeliveryRow row = deliveryRows.get(0);
                synchronized (row){
                    // 发送任务指令
                    try {
                        commandService.sendTask(StringUtils.isNotNull(row.getAgv()) ? row.getAgv() : deviceId, row);
                    } catch (JsonProcessingException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
}
